import 'package:lib_util/utils/utils.dart';
import 'package:objectbox/objectbox.dart';
import 'package:lib_database/objectbox.g.dart';
import 'package:lib_database/objectbox.dart';
import '../basemodel.dart';
import '../../network.dart';
import '../../config.dart';
import '../wallet_info_model/wallet_info_model.dart';

//native-主币  token20-以太系代币  token721-NFT  token1155-BTC的币种类型
enum TokenType { native, token20, token721, token1155, unknown }

@Entity()
class Token {
  @Id()
  int id;
  int walletInfoId;
  String contractType; //token类型
  String contract; //合约地址
  String name; //名称
  String symbol; //简称
  String? logo; //封面
  String? balance; //代币持仓数量
  String? priceusd; //代币美元价格
  String? valueusd; //代币总的美元价值
  String? change24h; //代币价格24小时涨跌幅
  bool enable;
  int decimals;
  String? totalSupply; //发行总量
  bool isAdded; //是否已经添加到钱包
  bool isCustom; //是否自定义代币
  bool isOperated; //该后台定义的token，是否曾经操作过添加或者移除钱包，操作过的token就不能在删除。
  int sortIndex; //后台排序的序号，-1为自定义，排在最后。

  Token(
      {this.id = 0,
      required this.walletInfoId,
      required this.contractType,
      required this.contract,
      required this.name,
      required this.symbol,
      this.logo,
      this.balance,
      this.priceusd,
      this.valueusd,
      this.change24h,
      this.enable = true,
      this.decimals = 0,
      this.totalSupply,
      this.isAdded = false,
      this.isCustom = false,
      this.isOperated = false,
      this.sortIndex = -1});

  @override
  String toString() {
    return 'Token{id: $id, walletInfoId: $walletInfoId, contractType: $contractType, contract: $contract, name: $name, symbol: $symbol, logo: $logo, balance: $balance, priceusd: $priceusd, valueusd: $valueusd, change24h: $change24h, enable: $enable, decimals: $decimals, isAdded: $isAdded}';
  }

  String getShowName() {
    return Utils.isNotEmpty(symbol) ? symbol : name;
  }

  String getFormatValueUsd() {
    return '\$${Utils.isEmpty(valueusd) ? '0.00' : Utils.formatStringBalance(valueusd!, fractionDigits: Config.balanceFixedNumUsingFiat)}';
  }

  String getFormatBalance() {
    return Utils.isEmpty(balance)
        ? '0.00'
        : Utils.formatStringBalance(balance!, fractionDigits: Config.balanceFixedNum);
  }

  Chain? getChain() {
    return getWalletInfo()!.getChain();
  }

  WalletInfo? getWalletInfo() {
    return ObjectBox().walletInfoModel.getWalletInfoById(walletInfoId);
  }

  bool isFungible() {
    return contractType == TokenType.native.name ||
        contractType == TokenType.token20.name ||
        contractType == TokenType.unknown.name;
  }
}

class TokenModel extends BaseModel<Token> {
  TokenModel(Box<Token> box) : super(box);

  Token? getTokenById(int id) {
    return box.get(id);
  }

  List<int> putTokenList(List<Token> tokens) {
    return box.putMany(tokens);
  }

  addToken(Token token) {
    return box.put(token, mode: PutMode.insert);
  }

  addTokenList(List<Token> tokens) {
    box.putMany(tokens, mode: PutMode.insert);
  }

  updateToken(Token token) {
    return box.put(token, mode: PutMode.update);
  }

  updateAsyncToken(Token token) {
    box.putAsync(token, mode: PutMode.update);
  }

  deleteToken(int tokenId) {
    box.remove(tokenId);
  }

  deleteTokenList(List<int> ids) {
    box.removeMany(ids);
  }

  List<Token> getTokenListByWalletInfoId(int walletInfoId) {
    return box.query(Token_.walletInfoId.equals(walletInfoId)).build().find();
  }

  List<Token> getTokenListAll() {
    return box.query().build().find();
  }

  List<Token> getEnableTokenListByWalletInfoId(int walletInfoId) {
    return box.query(Token_.walletInfoId.equals(walletInfoId) & Token_.enable.equals(true)).build().find();
  }

  //查询已添加到钱包的tokens
  List<Token> getIsAddedTokenListByWalletInfoId(int walletInfoId) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId) & Token_.enable.equals(true) & Token_.isAdded.equals(true))
        .build()
        .find();
  }
  //查询已添加到钱包的tokens
  List<Token> getIsAddedToken20ByWalletInfoId(int walletInfoId) {
    return box
        .query(Token_.contractType.equals(TokenType.token20.name) & Token_.walletInfoId.equals(walletInfoId) & Token_.enable.equals(true) & Token_.isAdded.equals(true))
        .build()
        .find();
  }

  //查询钱包的主币信息
  Token? getMainTokenByWalletInfoId(int walletInfoId) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId) &
            Token_.enable.equals(true) &
            Token_.contractType.equals('native') &
            Token_.isAdded.equals(true))
        .build()
        .findFirst();
  }

  Token? getTokenByWalletInfoIdSymbol(int id, String symbol) {
    return box
        .query(Token_.id.equals(id) & Token_.contractType.equals('native') & Token_.symbol.equals(symbol))
        .build()
        .findFirst();
  }

  List<Token> getToken20ListByWalletInfoId(int walletInfoId) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId) & Token_.contractType.equals(TokenType.token20.name))
        .build()
        .find();
  }

  List<Token> getAllTokens() {
    return box.query().build().find();
  }

  List<Token> getFungibleTokenListByWalletInfoId(int walletInfoId) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId)  & Token_.isAdded.equals(true) &
            Token_.contractType.equals(TokenType.native.name).or(Token_.contractType.equals(TokenType.token20.name)))
        .build()
        .find();
  }

  Token? getTokenByWalletInfoIdAndTokenContract(int walletInfoId, String contract) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId)  & Token_.isAdded.equals(true) & Token_.contract.equals(contract, caseSensitive: false))
        .build()
        .findFirst();
  }


  Token? getTokenByWIDSymNative(int walletInfoId, String symbol) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId) & Token_.contractType.equals('native') & Token_.symbol.equals(symbol))
        .build()
        .findFirst();
  }

  Token? getTokenByWIDContact(int walletInfoId, String contract) {
    return box
        .query(Token_.walletInfoId.equals(walletInfoId) & Token_.contract.equals(contract))
        .build()
        .findFirst();
  }
}
